import config from '@/config'
import { getPublicImageAssetsFile } from '@/utils/tools'

// 增大zoom
export const zoom2Big = () => {
    const maxZoom = config.mapInitOptions.maxZoom ?? 18
    if (window.glMap.getZoom() <= maxZoom) {
        window.glMap.zoomTo(window.glMap.getZoom() + 1)
    }
}

// 缩小zoom
export const zoom2Small = () => {
    const minZoom = config.mapInitOptions.minZoom ?? 4
    if (window.glMap.getZoom() >= minZoom) {
        window.glMap.zoomTo(window.glMap.getZoom() - 1)
    }
}

// 重置地图配置
export const resetMapView = () => {
    window.glMap.flyTo(config.mapInitOptions)
}

// 切换2d/3d
export const switch23D = (type: '2d' | '3d') => {
    window.glMap.flyTo({
        pitch: type === '2d' ? 0 : 45,
        zoom: window.glMap.getZoom(),
        speed: 0.2,
        curve: 1,
    })
}

// 移除图层
export const removeLayer = (layerId: string) => {
    if (window.glMap.getLayer(layerId)) {
        window.glMap.removeLayer(layerId)
    }
}

// 移除数据
export const removeSource = (source: string) => {
    if (window.glMap.getSource(source)) {
        window.glMap.removeSource(source)
    }
}

// 同时移除图层和数据，仅仅使用在source名称和layer名称相同的情况
export const removeLayerAndSource = (layerId: string) => {
    removeLayer(layerId)
    removeSource(layerId)
}

// 显示图层
export const showLayer = (layerId: string) => {
    if (window.glMap && window.glMap.getLayer(layerId)) {
        window.glMap.setLayoutProperty(layerId, 'visibility', 'visible')
    }
}

// 隐藏图层
export const hideLayer = (layerId: string) => {
    if (window.glMap && window.glMap.getLayer(layerId)) {
        window.glMap.setLayoutProperty(layerId, 'visibility', 'none')
    }
}

// 打开地图弹窗
export const showMapPop = (params: {
    VueComponent: any // vue组件
    properties: Record<string, any> // vue组件的props属性
    coordinates: number[] // 坐标
    offset?: [number, number]
}) => {
    // 清理老的
    if (window.popContent) {
        window.popContent.unmount()
        window.popContent = null
    }
    // 打开弹窗
    if (window.glPop) {
        window.glPop.remove()
        window.glPop = null
    }
    // 实例化vue组件
    window.popContent = createApp(params.VueComponent, {
        properties: params.properties,
    })
    // 生成dom
    const parent = document.createElement('div')
    const $el = window.popContent.mount(parent).$el
    // 偏移位置
    const offset = params.offset || [0, -12]
    window.glMap.easeTo({
        center: [params.coordinates[0], params.coordinates[1]],
        speed: 0.2,
        curve: 1.0,
        offset: [0, 150],
    })
    // 构建弹窗
    window.glPop = new window.mapboxgl.Popup({
        closeOnClick: true,
        closeButton: false,
        offset,
        className: 'map-pop-style',
    })
        .setLngLat(params.coordinates)
        .setDOMContent($el)
        .setMaxWidth('none')
        .addTo(window.glMap)
    window.glPop.once('close', () => {
        removeMapPop()
    })
}

// 移除地图弹窗
export const removeMapPop = () => {
    if (window.popContent) {
        window.popContent.unmount()
        window.popContent = null
    }
    if (window.glPop) {
        window.glPop.remove()
        window.glPop = null
    }
}

// 添加点位滑动提示
export const addPointLayerHoverTip = (layerId: string, nameField = 'name') => {
    if (window.glMap && window.glMap.getLayer(layerId)) {
        const layer = window.glMap.getLayer(layerId)
        layer._tip_mouseenter_handler = (e: any) => {
            window.glMap.getCanvas().style.cursor = 'pointer'
            const coordinates = e.features[0].geometry.coordinates.slice()
            const description = e.features[0].properties[nameField]

            while (Math.abs(e.lngLat.lng - coordinates[0]) > 180) {
                coordinates[0] += e.lngLat.lng > coordinates[0] ? 360 : -360
            }
            if (window.glTip) {
                window.glTip.remove()
            }
            window.glTip = new window.mapboxgl.Popup({
                className: 'map-tooltip-style',
                closeOnClick: false,
                closeButton: false,
            })
                .setLngLat(coordinates)
                .setHTML(description)
                .addTo(window.glMap)
            window.glMap.triggerRepaint()
        }
        window.glMap.on('mouseenter', layerId, layer._tip_mouseenter_handler)
        layer._tip_mouseleave_handler = () => {
            window.glMap.getCanvas().style.cursor = ''
            window.glTip.remove()
        }
        window.glMap.on('mouseleave', layerId, layer._tip_mouseleave_handler)
    }
}

// 移除滑动点位提示
export const removePointLayerHoverTip = (layerId: string) => {
    if (window.glMap && window.glMap.getLayer(layerId)) {
        const layer = window.glMap.getLayer(layerId)
        if (layer._tip_mouseenter_handler) {
            window.glMap.off('mouseenter', layerId, layer._tip_mouseenter_handler)
        }
        if (layer._tip_mouseleave_handler) {
            window.glMap.off('mouseleave', layerId, layer._tip_mouseleave_handler)
        }
    }
}

// 添加普通点位
export const addCommonPointLayer = (options: {
    layerId: string
    geojson: any
    onClick?: (e: any) => void
    hoverTipField?: string
    hoverTip?: boolean
}) => {
    // 添加数据资源
    window.glMap.addSource(options.layerId, {
        type: 'geojson',
        data: options.geojson,
    })
    // 添加图层资源
    const layer = window.glMap.addLayer({
        id: options.layerId,
        type: 'symbol',
        source: options.layerId,
        layout: {
            'icon-image': '{symbolImgName}', // 图片的source
            'icon-size': 0.65,
            'icon-ignore-placement': true, // 忽略碰撞检测
            visibility: 'visible'
        },
    })
    
    // 添加图层点位点击事件
    if (layer._click_handler) {
        window.glMap.off('click', options.layerId, layer._click_handler)
    }
    layer._click_handler = (e: any) => {
        options.onClick && options.onClick(e)
    }
    window.glMap.on('click', options.layerId, layer._click_handler)
    // 添加鼠标提示
    if (options.hoverTip) {
        removePointLayerHoverTip(options.layerId)
        addPointLayerHoverTip(options.layerId, options.hoverTipField ?? 'name')
    }
}

// 组合型移除
export const removeCombinedLayers = (layerIds: string[]) => {
    layerIds.forEach(item => {
        const layer = window.glMap.getLayer(item)
        if (layer) {
            // 移除点击事件
            if (layer._click_handler) {
                window.glMap.off('click', item, layer._click_handler)
            }
            // 移除鼠标提示
            removePointLayerHoverTip(item)

            // 移除图层
            removeLayerAndSource(item)
        }
    })
}
/**
 * 添加图片资源（图片需存放在 assets 目录下）
 * @param imgPath 图片路径
 * @param imgNameArr 图片文件名
 * @param format 图片文件后缀
 * @param type<String> 类型（例：gas(气) | water(水) | earth(土) | ...）
 *
 * 例：图片路径为 'assets/path/myPng.png'，
 * 调用：addImageToMap('path/', ['myPng'], '.png', 'myType')
 * 执行结果：在地图中添加名为 'myType-myPng' 的图片资源。
 */
export const addImageToMap = async (imgPath: string, imgNameArr: string[], format: string, type: string) => {
    const imageLoadPromise = [] as Promise<any>[]
    imgNameArr.forEach(imageName => {
        const imgSource = type === '' ? imageName : type + '-' + imageName
        // window._imgSourcePath 记录图片资源对应的存储路径
        if (!window._imgSourcePath) window._imgSourcePath = {}
        if (!Object.prototype.hasOwnProperty.call(window._imgSourcePath, imgSource)) window._imgSourcePath[imgSource] = imgPath + imageName + format
        if (!window.glMap.hasImage(imgSource)) {
        let image_data
        try {
            // image_data = new URL(`../../assets/${imgPath + imageName + format}`, import.meta.url).href
            image_data = getPublicImageAssetsFile(imgPath + imageName + format)
        } catch (e) {
            throw new Error(` (_addImageToMap:) 图标文件@/assets/${imgPath + imageName + format}不存在。\n${e}`)
        }
        const img = new Image()
        img.src = image_data
        imageLoadPromise.push(
            new Promise(resolve => {
            img.onload = e => {
                // 避免重复加载
                if (!window.glMap.hasImage(imgSource)) {
                window.glMap.addImage(imgSource, img)
                }
                resolve(e)
            }
            })
        )
        }
    })
    // 判断是否有图标资源需要加载
    if (imageLoadPromise.length !== 0) {
        await Promise.all(imageLoadPromise)
    }
}

/**
* 根据值获取因子等级对应的等级 对应优、良、轻度、中度、重度、严重--1,2,3,4,5,6
* @param {*} value
* @param {*} factorCode
*/
export function fcvToLevelNum(value: number|string, factorCode: string) {
  // 边界问题，如果 value 小于 0 直接返回0类型（灰色图标）
  let level = 0
  if (+value <= 0 || value === undefined || value === '--') return level
  const fcvArr = config.FACTORLEVEL[factorCode as keyof typeof config.FACTORLEVEL]
  fcvArr.map((arr: any, index: number) => {
    if (value > arr[0] && value <= arr[1]) {
      level = index + 1
    }
  })
  if (value === 0) level = 1
  return level
}

/**
 * 根据值获取因子等级对应的颜色
 * @param {*} value
 * @param {*} factorCode
 */
export function fcvToColor(value: number|string, factorCode: string) {
  // 边界问题，如果 value 小于 0 或者大于9999 直接返回灰色，温度不适用小于边界
  if ((+value < 0 && factorCode !== 'tem') || value === undefined || value === '--' || value == 0 || value === null || +value > 9999) return config.INVALIDCOLOR
  let color = ''
  const fcvArr = config.FACTORLEVEL[factorCode as keyof typeof config.FACTORLEVEL]
  let colors = config.LEVELCOLOR
  fcvArr.map((arr: any, index) => {
    if (value > arr[0] && value <= arr[1]) {
      color = colors[index]
    }
  })
  if (value === 0) color = colors[0]
  // 到这里 color 没填值说明超出字典预设，取最大颜色等级
  if (!color) {
    const len = config.FACTORLEVEL[factorCode as keyof typeof config.FACTORLEVEL].length
    color = colors[len - 1]
  }
  return color
}
